package com.yqg.protection.netty.encode;

import com.yqg.protection.netty.handler.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.util.List;

public class ProtocolDiscriminator extends ByteToMessageDecoder {

    private static final Logger log = LoggerFactory.getLogger(ProtocolDiscriminator.class);

    private final ApplicationContext applicationContext;

    public ProtocolDiscriminator(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        try {
            if (in.readableBytes() < 2) {
                log.debug("数据不足，等待更多数据: {}", in.readableBytes());
                return;
            }

            log.info("接收到数据，可读字节: {}", in.readableBytes());

            // 保存当前读指针位置
            in.markReaderIndex();

            // 读取2字节协议头（会移动读指针）
            byte[] header = new byte[2];
            in.readBytes(header);
            String headerHex = bytesToHex(header);
            log.info("协议头: {}", headerHex);

            // 恢复到标记位置（读指针回到开头）
            in.resetReaderIndex();

            DynamicProtocolHandler handler = null;
            String handlerName = null;

            switch (headerHex.toUpperCase()) {
                case "FD00":
                    handler = applicationContext.getBean(Sdf300RegisterHandler.class);
                    handlerName = "Sdf300RegisterHandler";
                    break;
                case "FE00":
                    handler = applicationContext.getBean(Sdf300Handler.class);
                    handlerName = "sdf300Handler";
                    break;
                case "4040":
                    handler = applicationContext.getBean(KeAn4040Handler.class);
                    handlerName = "kean4040Handler";
                    break;
                case "5D6C":
                    handler = applicationContext.getBean(KeAn5d6cHandler.class);
                    handlerName = "kean5d6cHandler";
                    break;
                default:
                    log.warn("未知协议头: {}", headerHex);
                    // 跳过整个缓冲区
                    in.skipBytes(in.readableBytes());
                    return;
            }

            log.info("添加/更新协议处理器: {}", handlerName);

            // 动态添加/更新处理器
            if (ctx.pipeline().get(handlerName) != null) {
                ctx.pipeline().remove(handlerName);
            }
            ctx.pipeline().addAfter(ctx.name(), handlerName, handler);

            // 消耗整个缓冲区数据
            int readableBytes = in.readableBytes();
            if (readableBytes > 0) {
                // 读取并传递整个数据包（会移动读指针）
                out.add(in.readRetainedSlice(readableBytes));
                log.info("已传递{}字节数据给处理器", readableBytes);
            }
        } catch (Exception e) {
            log.error("协议识别异常", e);
            ctx.close();
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("协议识别器异常", cause);
        ctx.close();
    }
}
